package mogiksaop.qliphoth.common.util.helpers;

import com.google.common.primitives.Primitives;
import mogiksaop.qliphoth.common.util.RegexPatterns;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Map;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;

public class CommonHelper {
	private static Field NBTMapField;
	private static Field NBTListField;
	private static Field ItemRegistryMapField;
	private static Field[] Fields;
	
	static {
		Fields = NBTTagCompound.class.getDeclaredFields();
		for (Field f : Fields) {
			if (Map.class.isAssignableFrom(f.getType())) {
				NBTMapField = f;
				NBTMapField.setAccessible(true);

				break;
			}
		}
		Fields = NBTTagList.class.getDeclaredFields();
		for (Field f : Fields) {
			if (java.util.List.class.isAssignableFrom(f.getType())) {
				NBTListField = f;
				NBTListField.setAccessible(true);
				break;
			}
		}
		Fields = net.minecraft.util.registry.RegistryNamespaced.class.getDeclaredFields();
		for (Field f : Fields) {
			if (Map.class.isAssignableFrom(f.getType())) {
				ItemRegistryMapField = f;
				ItemRegistryMapField.setAccessible(true);
				break;
			}
		}
	}

	public static void ensureIndex(ArrayList<?> a, int i) {
		while (a.size() <= i)
			a.add(null);
	}

	public static <T> T set(ArrayList<T> a, T value, int index) {
		if (a.size() <= index) {
			a.add(index, value);
			return null;
		}

		return (T) a.set(index, value);
	}

	public static <T> void insert(ArrayList<T> a, T value) {
		int nullIndex = a.indexOf(null);
		if (nullIndex == -1) {
			a.add(value);
		} else {
			a.set(nullIndex, value);
		}
	}

	public static <E> Map<String, E> getMap(NBTTagCompound nbt) {
		try {
			return (Map) NBTMapField.get(nbt);
		} catch (Exception e) {
			System.err.println(nbt);
			e.printStackTrace();

			return null;
		}
	}

	public static ArrayList<NBTBase> getList(NBTTagList nbt) {
		try {
			return (ArrayList) NBTListField.get(nbt);
		} catch (Exception e) {
			System.err.println(nbt);
			System.err.println(NBTListField);
			e.printStackTrace();

			return null;
		}
	}

	public static int indexOfAbsoluteMax(Object array) throws ClassCastException {
		int index = -1;
		int maxes = 0;
		Double max = null;
		for (int i = 0; i < Array.getLength(array); i++) {
			Number n = (Number) Array.get(array, i);
			if (max == null || n.doubleValue() > max.doubleValue()) {
				max = Double.valueOf(n.doubleValue());
			}
		}
		for (int i = 0; i < Array.getLength(array); i++) {
			Number n = (Number) Array.get(array, i);
			if (n.doubleValue() == max.doubleValue()) {
				maxes++;
				index = i;
			}
			if (maxes > 1)
				return -1;
		}
		return index;
	}

	public static Object[] wrapperArray(Object aprimitive) {
		if (!aprimitive.getClass().isArray())
			throw new IllegalArgumentException("The variable 'primitiveArray' must ACTUALLY BE AN ARRAY!");
		Class cl = aprimitive.getClass().getComponentType();
		if (!cl.isPrimitive())
			return (Object[]) aprimitive;
		cl = Primitives.wrap(cl);
		Object awrapper = Array.newInstance(cl, Array.getLength(aprimitive));
		for (int i = 0; i < Array.getLength(aprimitive); i++) {
			Array.set(awrapper, i, Array.get(aprimitive, i));
		}
		return (Object[]) awrapper;
	}

	public static <K, V> Map<K, V> addEntries(Map<K, V> map, K[] keys, V[] vals) {
		for (int i = 0; i < keys.length; i++) {
			map.put(keys[i], vals[i]);
		}
		return map;
	}

	@SuppressWarnings("unchecked")
	public static <K, V> Map<K, V> addEntries(Map<K, V> map, Object[] kvs) {
		for (int i = 0; i < kvs.length / 2; i++) {
			map.put((K)kvs[i * 2], (V)kvs[i * 2 + 1]);
		}
		return map;
	}

	public static <V> V getIgnoreCase(Map<String, V> map, String key) {
		if (key == null)
			return (V) map.get(null);
		for (Map.Entry<String, V> entry : map.entrySet()) {
			if (key.equalsIgnoreCase((String) entry.getKey())) {
				return (V) entry.getValue();
			}
		}
		return null;
	}

	public static String textInQuotes(String str) {
		return RegexPatterns.REMOVEQUOTES.matcher(str).replaceAll("$1").trim();
	}
}
